/*

  xmunipack - homepage


  Copyright © 2009-2011 F.Hroch (hroch@physics.muni.cz)

  This file is part of Munipack.

  Munipack is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  Munipack is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with Munipack.  If not, see <http://www.gnu.org/licenses/>.


  Notes.

  * Forward History is randomly functional (bug in wx?)
  * Stop button is inactive, wx doesn't offers callback
  * Statusbar is not cleared when pointer leaving link, there is no callback
  * click to ftp link doesn't work, probably unimplemented by wx
  * Closing window during load/rendering leads to a crash when one finish.

*/

#include "xmunipack.h"
#include <wx/wx.h>
#include <wx/imaglist.h>
#include <wx/filename.h>
#include <wx/html/htmlwin.h>
#include <wx/fs_inet.h>
#include <wx/aboutdlg.h>
#include <wx/url.h>
#include <wx/stdpaths.h>
#include <wx/txtstrm.h>
#include <wx/wfstream.h>
#include <wx/sstream.h>

#define GPL_PART1 "The Munipack is free software; you can redistribute\nit and/or modify it under the terms of the GNU\nGeneral Public License as published by the Free\nSoftware Foundation; either version 3 of the\nLicense, or (at your option) any later version.\n\n"
#define GPL_PART2 "The Munipack is distributed in the hope that it\nwill be useful, but WITHOUT ANY WARRANTY;\nwithout even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR\nPURPOSE.  See the GNU General Public License for\nmore details.\n\n"
#define GPL_PART3 "You should have received a copy of the GNU\nGeneral Public License along with the Munipack;\nif not, write to the Free Software Foundation, Inc.,\n51 Franklin Street, Fifth Floor,Boston,\nMA  02110-1301  USA"

BEGIN_EVENT_TABLE(MuniHelp, wxFrame)
EVT_CLOSE(MuniHelp::OnClose)
EVT_SIZE(MuniHelp::OnSize)
EVT_MENU(wxID_OPEN, MuniHelp::FileOpen)
EVT_MENU(wxID_CLOSE, MuniHelp::FileClose)
EVT_MENU(wxID_BACKWARD, MuniHelp::GoBack)
EVT_MENU(wxID_FORWARD, MuniHelp::GoForward)
EVT_MENU(wxID_HOME, MuniHelp::GoHome)
//EVT_MENU(wxID_STOP, MuniHelp::ViewStop)
EVT_MENU(wxID_REFRESH, MuniHelp::ViewReload)
EVT_MENU(ID_EXTERNAL, MuniHelp::DefaultBrowser)
EVT_MENU(wxID_ABOUT, MuniHelp::HelpAbout)
EVT_TOOL(wxID_BACKWARD, MuniHelp::GoBack)
EVT_TOOL(wxID_FORWARD, MuniHelp::GoForward)
//EVT_BUTTON(wxID_STOP, MuniHelp::ViewStop)
EVT_TOOL(wxID_HOME, MuniHelp::GoHome)
EVT_TOOL(wxID_REFRESH, MuniHelp::GoUrl)
EVT_TEXT_ENTER(ID_ENTRY, MuniHelp::GetUrl)
EVT_HTML_CELL_HOVER(ID_BROWSER, MuniHelp::PrintHref)
EVT_HTML_LINK_CLICKED(ID_BROWSER, MuniHelp::ClickedUrl)
END_EVENT_TABLE()


MuniHelp::MuniHelp(MuniConfig *c): 
wxFrame(NULL, wxID_ANY, wxT("Munipack"), wxDefaultPosition, 
	c->help_size,wxDEFAULT_FRAME_STYLE), 
  web(new wxHtmlWindow(this,ID_BROWSER)),home(wxT(HOMEPAGE)), turl(0),
  config(c),tbar(0),menuGo(new wxMenu), menuView(new wxMenu)
{
  SetIcon(config->munipack_icon);

  // look for local html directory
  wxPathList paths;
  if( wxGetEnv("MUNIPACK_HTML",0) )
    paths.AddEnvList("MUNIPACK_HTML");

#ifdef MUNIPACK_HTML_PATH
  paths.Add(wxString(MUNIPACK_HTML_PATH));
#endif

  wxString cpath = paths.FindValidPath(wxT("munipack.html"));
  if( ! cpath.IsEmpty() )
    home = cpath;


  // menu
  wxMenu *menuFile = new wxMenu;
  wxMenu *menuEdit = new wxMenu;
  wxMenuBar *menuBar = new wxMenuBar();

  menuFile->Append(wxID_OPEN);
  menuFile->AppendSeparator();
  menuFile->Append(wxID_CLOSE);
#ifdef __WXMAC__
  menuFile->Append(wxID_EXIT);
#endif

  menuEdit->Append(wxID_PREFERENCES);

  menuView->Append(wxID_STOP);
  menuView->Append(wxID_REFRESH);

  menuGo->Append(wxID_BACKWARD);
  menuGo->Append(wxID_FORWARD);
  menuGo->Append(wxID_HOME);
  menuGo->Append(ID_EXTERNAL, wxT("&Open in default browser"));

  wxMenu *menuHelp = new wxMenu;
  menuHelp->Append(wxID_ABOUT);

  menuBar->Append(menuFile, wxT("&File"));
  menuBar->Append(menuEdit, wxT("&Edit"));
  menuBar->Append(menuView, wxT("&View"));
  menuBar->Append(menuGo, wxT("&Go"));
#ifndef __WXMAC__
  menuBar->Append(menuHelp, wxT("&Help"));
#endif

  SetMenuBar(menuBar);

  // status bar
  CreateStatusBar(1);
  SetStatusText(wxT("Browse homepage"));

  // toolbar
  tbar = CreateToolBar(wxTB_TEXT);
  MuniArtIcons ico(wxART_TOOLBAR,wxSize(22,22));

  tbar->AddTool(wxID_BACKWARD,wxT("Back"),ico.Icon(wxART_GO_BACK),
		wxT("Go to previous page"));
  tbar->AddTool(wxID_FORWARD,wxT("Forward"),ico.Icon(wxART_GO_FORWARD),
		wxT("Go to next seen page"));
  tbar->AddTool(wxID_STOP,wxT("Stop"),ico.Icon(wxT("stop")),
		wxT("Stop loading (Currently not implemented)"));
  tbar->AddTool(wxID_HOME,wxT("Home"),ico.Icon(wxART_GO_HOME),
		wxT("Go to Munipack's homepage"));
  tbar->AddTool(wxID_REFRESH,wxT("Refresh"),ico.Icon(wxT("view-refresh")),
		wxT("Reload current page"));

  turl = new wxTextCtrl(tbar,ID_ENTRY,home,wxDefaultPosition,
			wxDefaultSize,wxTE_PROCESS_ENTER);
  tbar->AddControl(turl);
  tbar->Realize();

  tbar->EnableTool(wxID_BACKWARD,false);
  tbar->EnableTool(wxID_FORWARD,false);
  tbar->EnableTool(wxID_STOP,false);
  menuGo->Enable(wxID_BACKWARD,false);
  menuGo->Enable(wxID_FORWARD,false);
  menuView->Enable(wxID_STOP,false);
  menuEdit->Enable(wxID_PREFERENCES,false);

  // sizer
  wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
  topsizer->Add(web,wxSizerFlags(1).Expand());
  SetSizer(topsizer);

  // html page
  web->LoadPage(home);
}

MuniHelp::~MuniHelp() 
{ 
  config->help_size = GetSize(); 
}


void MuniHelp::OnClose(wxCloseEvent& event)
{
  Destroy();
}

void MuniHelp::OnSize(wxSizeEvent& event)
{
  wxSize size(GetClientSize());
  wxSize margins(tbar->GetMargins());
  wxSize tool(tbar->GetToolSize());
  int n(tbar->GetToolsCount()+1);

  int w = size.GetWidth() - 2*n*margins.GetWidth() - n*tool.GetWidth() 
    - 2*n*tbar->GetToolSeparation() - 2*tool.GetWidth();
  turl->SetSize(w,-1);

  event.Skip();
}


void MuniHelp::FileClose(wxCommandEvent& WXUNUSED(event))
{
  Destroy();
}

void MuniHelp::FileOpen(wxCommandEvent& WXUNUSED(event))
{
  SetStatusText(wxT("Open a html file."));
  wxFileDialog select(this,wxT("Choose file"),wxT(""),wxT(""),
		      wxT("HTML files (*.html)|*.html| All files (*)|*"),
		      wxFD_FILE_MUST_EXIST|wxFD_CHANGE_DIR);
  if (select.ShowModal() == wxID_OK ) {
    SetStatusText(wxT("Loading file: ")+select.GetPath());
    web->LoadFile(select.GetPath());
    turl->SetValue(web->GetOpenedPage());
    SetStatusText(wxT(""));
    UpdateControls();
  }
}

void MuniHelp::GoBack(wxCommandEvent& WXUNUSED(event))
{
  web->HistoryBack();
  turl->SetValue(web->GetOpenedPage());
}

void MuniHelp::GoForward(wxCommandEvent& WXUNUSED(event))
{
  web->HistoryForward();
  turl->SetValue(web->GetOpenedPage());
}

void MuniHelp::GoHome(wxCommandEvent& WXUNUSED(event))
{
  SetStatusText(wxT("Loading homepage..."));
  web->LoadPage(home);
  turl->SetValue(web->GetOpenedPage());
  SetStatusText(wxT(""));
  UpdateControls();
}

void MuniHelp::ViewStop(wxCommandEvent& WXUNUSED(event))
{
  SetStatusText(wxT("Not implemented yet."));  
}

void MuniHelp::ViewReload(wxCommandEvent& WXUNUSED(event))
{
  SetStatusText(wxT("Reloading ..."));
  web->LoadPage(web->GetOpenedPage());
  turl->SetValue(web->GetOpenedPage());
  SetStatusText(wxT(""));
  UpdateControls();
}

void MuniHelp::GetUrl(wxCommandEvent& event)
{
  wxString a(event.GetString());
  if( ! a.StartsWith(wxT("http://")) )
      a = wxT("http://") + a;
  wxURL url(a);
  switch (url.GetError()) {
  case wxURL_NOERR: break;
  case wxURL_NOPATH: break;
  default: SetStatusText(wxT("An unknown address string.")); return;
  }
  web->LoadPage(a);
  UpdateControls();
}

void MuniHelp::SelUrl(wxCommandEvent& event)
{
  web->LoadPage(event.GetString());
  UpdateControls();
}

void MuniHelp::GoUrl(wxCommandEvent& WXUNUSED(event))
{
  SetStatusText(wxT("Loading ..."));
  web->LoadPage(turl->GetValue());
  SetStatusText(wxT(""));
  UpdateControls();
}

void MuniHelp::PrintHref(wxHtmlCellEvent& cell)
{
  wxHtmlCell *link = cell.GetCell();
  wxHtmlLinkInfo *info = link->GetLink();

  if( info ) {
    wxString href(info->GetHref());
    SetStatusText(href);
  }
}

void MuniHelp::ClickedUrl(wxHtmlLinkEvent& linkinfo)
{
  SetStatusText(wxT("Loading ..."));
  wxHtmlLinkInfo info = linkinfo.GetLinkInfo();
  wxString href(info.GetHref());
  web->LoadPage(href);
  turl->SetValue(web->GetOpenedPage());
  tbar->EnableTool(wxID_BACKWARD,false);
  SetStatusText(wxT(""));
  UpdateControls();
}

void MuniHelp::DefaultBrowser(wxCommandEvent& WXUNUSED(event))
{
  wxLaunchDefaultBrowser(web->GetOpenedPage());
}

void MuniHelp::UpdateControls()
{
  if( web->HistoryCanBack() ) {
    tbar->EnableTool(wxID_BACKWARD,true);
    menuGo->Enable(wxID_BACKWARD,true);
  }
    
  if( web->HistoryCanForward() ) {
    tbar->EnableTool(wxID_FORWARD,true);
    menuGo->Enable(wxID_FORWARD,true);
  }
}

void MuniHelp::HelpAbout(wxCommandEvent& WXUNUSED(event))
{
  MuniAbout();
}

MuniAbout::MuniAbout()
{
  // look for CREDITS

  wxArrayString p;

#ifdef __WXDEBUG__
  p.Add(".");
  p.Add("..");
#endif

  wxPathList paths(p);
  if( wxGetEnv("MUNIPACK_DOC",0) )
    paths.AddEnvList("MUNIPACK_DOC");

#ifdef MUNIPACK_DOC_PATH
  paths.Add(wxString(MUNIPACK_DOC_PATH));
#endif

  wxString cpath = paths.FindValidPath("CREDITS");

  // read CREDITS
  wxString xcredits;
  if( ! cpath.IsEmpty() ) {
    wxFileInputStream credits(cpath);
    wxTextInputStream text(credits);
    wxStringOutputStream buf;
    buf.Write(credits);
    xcredits = buf.GetString();
  }

  wxAboutDialogInfo info;
  info.SetName(INFOTEXT);
  info.SetVersion(XVERSION);
  info.SetDescription(INFOTEXTFULL);
  info.SetCopyright(COPYLEFT);
  info.SetWebSite(HOMEPAGE);
  if( ! xcredits.IsEmpty() ) 
    info.AddDeveloper(xcredits);
  wxString g;
  g += GPL_PART1;
  g += GPL_PART2;
  g += GPL_PART3;
  info.SetLicence(g);
  wxAboutBox(info);
}
